package com.swak.vertx.protocol.http.adapter;

import java.util.concurrent.CompletionStage;
import java.util.function.BiConsumer;

import com.swak.vertx.protocol.http.ResultHandler;
import com.swak.vertx.protocol.http.RoutingContexts;

import io.vertx.core.impl.ContextInternal;

/**
 * 结果处理: 作为第一个处理，调用后续的处理，并监控输出
 * 
 * @author DELL
 */
public class ResultAdapter extends AbstractAdapter {

	private ResultHandler resultHandler;
	private final BiConsumer<Context, Throwable> handle;
	private final OnContext onContext;

	public ResultAdapter(ResultHandler resultHandler) {
		this.resultHandler = resultHandler;
		this.handle = this::handle;
		this.onContext = this::handleOnContext;
	}

	@Override
	public CompletionStage<Context> handle(Context context) {
		this.next(context).whenComplete(this.handle);
		return context;
	}

	/**
	 * 失败的处理
	 * 
	 * @param context
	 * @param error
	 */
	protected void handle(Context context, Throwable error) {
		ContextInternal currContext = RoutingContexts.context(context.$context);
		if (currContext != null) {
			currContext.runOnContext((vo) -> this.onContext.handle(context, error));
		} else {
			this.onContext.handle(context, error);
		}
	}

	protected void handleOnContext(Context context, Throwable error) {
		Throwable $error = error == null ? context.$error : error;
		try {
			this.resultHandler.handleResult(context.$result, $error, context.$context);
		} catch (Throwable e) {
			this.resultHandler.handleError(e, context.$context);
		} finally {
			context.$complete($error);
		}
	}

	/**
	 * 在 Context 继续处理
	 * 
	 * @author DELL
	 */
	@FunctionalInterface
	interface OnContext {
		void handle(Context context, Throwable error);
	}
}
